import { getTokensMetaByContractAndId } from '../../../../api/walletsAPI.ts';
import { readWishlist } from '../../utils.ts';

import type { MetadataList, NFTDetails, NFTsListType, Offer } from '../../../../types.ts';

type PromiseToGetTokensProps = {
    id: bigint;
    type: NFTsListType;
    NFTs: NFTDetails[];
    initiatorAddress: string;
    receiverAddress: string;
}

export const createPromiseToGetTokens = ({
    id,
    type,
    NFTs,
    initiatorAddress,
    receiverAddress,
}: PromiseToGetTokensProps) =>{
    return new Promise<{
        offerId: bigint;
        data: {
            offersList: Record<NFTsListType, MetadataList>;
            initiatorAddress: string;
            receiverAddress: string;
        }
        
    } >(resolve => {
        getTokensMetaByContractAndId(NFTs)
            .then((listOfNFTs) => {

                const offersList = { [type]: listOfNFTs } as Record<NFTsListType, MetadataList>;
                resolve({ offerId: id, data: { offersList, initiatorAddress, receiverAddress }  });
            });
    });
};

export const getMetadataFromOffers = async (offers: Offer[]) => {

    const arrayOfGetOffersNFTsFn = [];

    for (const offer of offers) {

        const initiatorWishlist = readWishlist(offer.name);

        const getDesiredNFTs = createPromiseToGetTokens({
            id: offer.id,
            initiatorAddress: offer.initiator.account,
            receiverAddress: offer.recipient.account,
            type: 'desired',
            NFTs: initiatorWishlist,
        });

        const getSuggestedNFTs = createPromiseToGetTokens({
            id: offer.id,
            initiatorAddress: offer.initiator.account,
            receiverAddress: offer.recipient.account,
            type: 'suggested',
            NFTs: offer.initiator.items,
        });

        arrayOfGetOffersNFTsFn.push(getDesiredNFTs, getSuggestedNFTs);
    }

    const arrayOfResult = await Promise.all(arrayOfGetOffersNFTsFn);

    const offersWithNFTs = new Map();

    for (const el of arrayOfResult) {
        const offerData = offersWithNFTs.get(el.offerId);

        if (offerData) {
            const offersList = {
                ...offerData.offersList,
                ...el.data.offersList,
            };
            offersWithNFTs.set(el.offerId, { ...offerData, offersList });
        } else {
            offersWithNFTs.set(el.offerId, el.data);
        }
    }

    return Array.from(offersWithNFTs);
};